package at.fhooe.mc.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import at.fhooe.mc.control.manual.IManualControl;
import at.fhooe.mc.data.ControlMode;
import at.fhooe.mc.data.DirectionType;
import at.fhooe.mc.data.ElevatorData;
import at.fhooe.mc.data.FloorData;
import at.fhooe.mc.data.SystemData;
import at.fhooe.mc.model.ElevatorControlCenterObserver;

public class ElevatorControlCenterView extends JFrame implements
		ElevatorControlCenterObserver
{

	private IManualControl manualControl;

	private ArrayList<FloorData> floors;
	private ArrayList<ElevatorData> elevators;

	int numberOfFloors, floorHeight;

	int currentElevatorIndex = 0;

	private JPanel jplMaster, jplRightPanel, jplLeftPanel, jplTop, jplMid,
			jplButtom, jplIconView, jplInsideElevator;

	private ArrayList<JTrianglePanelUpSmall> floorPanelsUp;
	private ArrayList<JTrianglePanelDownSmall> floorPanelsDown;
	private ArrayList<JCirclePanel> trueFalsefloorsInside;

	private JLabel txtElevatorAcc, txtElevatorCapacity, txtElevatorPosition,
			txtElevatorSpeed, txtElevatorWeight, txtNewTarget, txtManualOrAuto,txtElevatorFloorHeight;

	private JLabel outputElevatorCapacity, outputElevatorPosition,
			outputElevatorSpeed, outputElevatorWeight, outputElevatorAcc, outputElevatorFloorHeight;

	private JButton btnGo, btnChange;

	private JTextField inputTargetFloor;

	private JTrianglePanelUp bigTriangleUp;
	private JTrianglePanelDown bigTriangleDown;
	private JTrianglePanelSquare sqaureDoors;

	private int intManualOrAuto;
	private Integer currentTargetFloor, currentFloor, currentDirection,
			minElevatorFloor, maxElevatorFloor;

	private JComboBox manualControlBox;

	public ElevatorControlCenterView(IManualControl _manualControl)
	{

		floorPanelsUp = new ArrayList<JTrianglePanelUpSmall>();
		floorPanelsDown = new ArrayList<JTrianglePanelDownSmall>();
		trueFalsefloorsInside = new ArrayList<JCirclePanel>();

		manualControl = _manualControl;

		currentTargetFloor = 0;
		currentFloor = 0;
		currentDirection = 2; // 0 up, 1 down , 2 not committed
		intManualOrAuto = 1; // 0 = manual, 1 = auto

		numberOfFloors = 10;
		// the floors are 1 - 10 but uses 0 - 9

		minElevatorFloor = 1;
		maxElevatorFloor = 10;

		// --- left panel

		jplMaster = new JPanel();
		jplLeftPanel = new JPanel();
		jplTop = new JPanel();
		jplMid = new JPanel();
		jplButtom = new JPanel();
		jplIconView = new JPanel();

		jplMaster.setLayout(new BorderLayout());
		jplTop.setLayout(new GridLayout(3, 2, 2, 2));
		jplMid.setLayout(new GridLayout(1, 2, 2, 2));
		jplButtom.setLayout(new GridLayout(1, 3, 2, 2));

		txtElevatorAcc = new JLabel("Acceleration : ");
		txtElevatorCapacity = new JLabel("Capacity : ");
		txtElevatorFloorHeight = new JLabel("Floor Height :");
		txtElevatorPosition = new JLabel("Position :");
		txtElevatorSpeed = new JLabel("Speed :");
		txtElevatorWeight = new JLabel("Weight :");
		txtNewTarget = new JLabel("New target :");
		txtManualOrAuto = new JLabel("On Manual Mode");
		txtManualOrAuto.setName("changeModeLabel");


		outputElevatorCapacity = new JLabel();
		outputElevatorPosition = new JLabel();
		outputElevatorSpeed = new JLabel();
		outputElevatorWeight = new JLabel();
		outputElevatorAcc = new JLabel();
		outputElevatorFloorHeight = new JLabel();

		jplTop.add(txtElevatorAcc, BorderLayout.LINE_START);
		jplTop.add(outputElevatorAcc, BorderLayout.AFTER_LAST_LINE);

		jplTop.add(txtElevatorCapacity, BorderLayout.LINE_START);
		jplTop.add(outputElevatorCapacity, BorderLayout.AFTER_LAST_LINE);

		jplTop.add(txtElevatorFloorHeight, BorderLayout.LINE_START);
		jplTop.add(outputElevatorFloorHeight, BorderLayout.AFTER_LAST_LINE);

		jplTop.add(txtElevatorWeight, BorderLayout.LINE_START);
		jplTop.add(outputElevatorWeight, BorderLayout.AFTER_LAST_LINE);

		jplTop.add(txtElevatorPosition, BorderLayout.LINE_START);
		jplTop.add(outputElevatorPosition, BorderLayout.AFTER_LAST_LINE);

		jplTop.add(txtElevatorSpeed, BorderLayout.LINE_START);
		jplTop.add(outputElevatorSpeed, BorderLayout.AFTER_LAST_LINE);

		jplTop.setSize(400, 40);

		btnGo = new JButton("GO!");

		btnChange = new JButton("Change Mode");

		inputTargetFloor = new JTextField("3", 10);

		jplMid.add(btnChange, BorderLayout.LINE_START);
		jplMid.add(txtManualOrAuto, BorderLayout.AFTER_LAST_LINE);
		jplMid.setSize(400, 40);

		jplButtom.add(txtNewTarget, BorderLayout.LINE_START);
		jplButtom.add(inputTargetFloor, BorderLayout.AFTER_LAST_LINE);
		jplButtom.add(btnGo, BorderLayout.AFTER_LAST_LINE);

		manualControlBox = new JComboBox(DirectionType.values());
		manualControlBox.setSelectedIndex(2);

		jplButtom.add(manualControlBox);

		jplButtom.setSize(400, 40);

		jplLeftPanel.setLayout(new BoxLayout(jplLeftPanel, BoxLayout.PAGE_AXIS));

		jplLeftPanel.add(jplTop);
		jplLeftPanel.add(new JSeparator(SwingConstants.HORIZONTAL));
		jplMid.setBorder(BorderFactory.createEmptyBorder(0, 0, 20, 0));
		jplLeftPanel.add(jplMid);
		jplLeftPanel.add(new JSeparator(SwingConstants.HORIZONTAL));

		jplLeftPanel.add(jplButtom);

		// --- right panel

		jplRightPanel = new JPanel();

		jplRightPanel.setPreferredSize(new Dimension(50, 250));

		GridBagLayout gridbag = new GridBagLayout();

		jplRightPanel.setLayout(gridbag);

		for (int q = numberOfFloors - 1; q >= 0; q--)
		{

			addLabelToPanel("" + (q + 1), new GridBagConstraints(0,
				numberOfFloors - 1 - q, 1, 1, 0, 0, GridBagConstraints.CENTER,
				GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));

			makeArrows(new GridBagConstraints(1, numberOfFloors - 1 - q, 1, 1,
				1, 0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
				new Insets(6, 0, 2, 0), 0, 0));

			// floorPanelsDown.get(q-1).setTrianglecolor(Color.white);

		}

		// ------------------- Elevator Icon View
		jplInsideElevator = new JPanel();
		jplInsideElevator.setLayout(new GridLayout(numberOfFloors / 2, 2, 1, 1));

		for (int q = numberOfFloors - 1; q >= 0; q--)
		{

			JCirclePanel circle = new JCirclePanel();
			circle.setFloorNumber(q + 1);
			trueFalsefloorsInside.add(circle);
			jplInsideElevator.add(circle);
		}

		jplIconView.setLayout(new GridBagLayout());

		bigTriangleUp = new JTrianglePanelUp();
		bigTriangleUp.setPreferredSize(new Dimension(100, 55));
		bigTriangleDown = new JTrianglePanelDown();
		bigTriangleDown.setPreferredSize(new Dimension(100, 55));
		sqaureDoors = new JTrianglePanelSquare();
		sqaureDoors.setPreferredSize(new Dimension(105, 100));
		jplInsideElevator.setPreferredSize(new Dimension(100, 105));
		jplIconView.add(bigTriangleUp, new GridBagConstraints(1, 0, 1, 1, 0, 0,
			GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,
				0, 0, 0), 0, 0));
		jplIconView.add(jplInsideElevator, new GridBagConstraints(0, 1, 1, 1,
			0, 0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
			new Insets(0, 0, 0, 0), 0, 0));
		jplIconView.add(sqaureDoors, new GridBagConstraints(1, 1, 1, 1, 0, 0,
			GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,
				0, 0, 0), 0, 0));
		jplIconView.add(bigTriangleDown, new GridBagConstraints(1, 2, 1, 1, 0,
			0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
				0, 0, 0, 0), 0, 0));
		jplIconView.add(new JPanel(), new GridBagConstraints(0, 3, 2, 1, 0, 0,
			GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,
				0, 0, 0), 1, 1));

		// --- put together panel

		jplIconView.setPreferredSize(new Dimension(200, 400));

		jplMaster.add(jplLeftPanel, BorderLayout.WEST);

		jplMaster.add(jplIconView, BorderLayout.CENTER);

		jplMaster.add(jplRightPanel, BorderLayout.EAST);

		getContentPane().add(jplMaster, BorderLayout.CENTER);
		requestFocus();

		updateTextFields();

		TextFieldHandler handler = new TextFieldHandler();

		btnGo.addActionListener(handler);
		btnChange.addActionListener(handler);
		inputTargetFloor.addActionListener(handler);
		manualControlBox.addActionListener(handler);

		this.setTitle("Advanced Elevator Control Center");
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setPreferredSize(new Dimension(900, 400));

		this.setLocationRelativeTo(null); // puts the gui in the midle of the
											// screen

		pack();

		setVisible(true);

	}

	public Integer getCurrentDirectionInt(){

		return currentDirection;

	}

	protected void addLabelToPanel(String name, GridBagConstraints c)
	{
		JLabel label = new JLabel(name);
		label.setPreferredSize(new Dimension(50, 80));
		jplRightPanel.add(label, c);
	}

	protected void makeArrows(GridBagConstraints c)
	{
		JTrianglePanelUpSmall triangleUp = new JTrianglePanelUpSmall();
		triangleUp.setPreferredSize(new Dimension(50, 40));

		floorPanelsUp.add(triangleUp);

		JTrianglePanelDownSmall triangleDown = new JTrianglePanelDownSmall();
		triangleDown.setPreferredSize(new Dimension(50, 40));

		floorPanelsDown.add(triangleDown);

		JPanel pan = new JPanel();
		pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS));
		pan.add(triangleUp);
		pan.add(triangleDown);

		jplRightPanel.add(pan, c);

	}

	private void updateTextFields()
	{

		if (currentDirection == 0)
		{

			bigTriangleUp.setTrianglecolorOn(true,
				currentTargetFloor.toString());
			bigTriangleDown.setTrianglecolorOn(false, "");

		}
		else if (currentDirection == 1)
		{

			bigTriangleDown.setTrianglecolorOn(true,
				currentTargetFloor.toString());
			bigTriangleUp.setTrianglecolorOn(false, "");

		}
		else
		{

			bigTriangleUp.setTrianglecolorOn(false, "");
			bigTriangleDown.setTrianglecolorOn(false, "");
		}

	}

	@Override
	public void updateNewValues(SystemData data)
	{

		floorHeight = data.getFloorHeight();
		floors = data.getFloors();
		elevators = data.getElevators();

		// manualControl.manualDirection(currentElevatorIndex,(DirectionType)manualControlBox.getSelectedItem());

		if (intManualOrAuto == 1)
		{

			currentTargetFloor = (data.getElevators().get(currentElevatorIndex).getCurrentTarget() + 1);

		}

		if (numberOfFloors != floors.size())
		{
			numberOfFloors = floors.size();
		}

		outputElevatorCapacity.setText(elevators.get(currentElevatorIndex).getElevatorCapacity() + " Persons");
		outputElevatorFloorHeight.setText(floorHeight + " feet");
		outputElevatorPosition.setText(elevators.get(currentElevatorIndex).getElevatorPosition() + " feet");
		outputElevatorSpeed.setText(elevators.get(currentElevatorIndex).getElevatorSpeed() + " feet/s");
		outputElevatorWeight.setText(elevators.get(currentElevatorIndex).getElevatorWeight() + " lbs");
		outputElevatorAcc.setText(elevators.get(currentElevatorIndex).getElevatorAccel() + " feet/s^2");

		if (elevators.get(currentElevatorIndex).getCommittedDirection().equals(
			DirectionType.UNCOMMITTED))
		{

			currentDirection = 2;

		}
		if (elevators.get(currentElevatorIndex).getCommittedDirection().equals(
			DirectionType.DOWN))
		{

			currentDirection = 1;

		}
		if (elevators.get(currentElevatorIndex).getCommittedDirection().equals(
			DirectionType.UP))
		{

			currentDirection = 0;

		}

		currentFloor = elevators.get(currentElevatorIndex).getElevatorFloor() + 1;

		for (int i = 0; i < floors.size(); i++)
		{ // for loop for the up down lights on the right side

			if (floors.get(i).isFloorButtonDown())
			{

				floorPanelsDown.get(numberOfFloors - i - 1).setTrianglecolor(
					Color.green);

			}
			else
			{

				floorPanelsDown.get(numberOfFloors - i - 1).setTrianglecolor(
					Color.gray);

			}

			if (floors.get(i).isFloorButtonUp())
			{

				floorPanelsUp.get(numberOfFloors - i - 1).setTrianglecolor(
					Color.green);

			}
			else
			{

				floorPanelsUp.get(numberOfFloors - i - 1).setTrianglecolor(
					Color.gray);

			}

		}

		for (int i = 0; i < floors.size(); i++)
		{ // for loop for the inside elevator buttons

			if (elevators.get(currentElevatorIndex).getElevatorButton()[i] == true)
			{

				trueFalsefloorsInside.get(numberOfFloors - i - 1).setTrianglecolor(
					true);

			}
			else
			{

				trueFalsefloorsInside.get(numberOfFloors - i - 1).setTrianglecolor(
					false);

			}

		}

		changeVisibility(data.getElevators().get(currentElevatorIndex).getMode() == ControlMode.AUTOMATIC);

		sqaureDoors.openCloseDoors(
			elevators.get(currentElevatorIndex).getElevatorDoorStatus(),
			currentFloor);

		// update information from ecc
		// minElevatorFloor, maxElevatorFloor ....

		// change currentDirection to right direction from ECC

		updateTextFields();
	}

	private void changeVisibility(boolean visible)
	{
		if (visible)
		{

			txtManualOrAuto.setText("On Auto Mode");
			intManualOrAuto = 1;
		}
		else
		{

			txtManualOrAuto.setText("On Manual Mode");
			intManualOrAuto = 0;
		}

		inputTargetFloor.setVisible(!visible);
		btnGo.setVisible(!visible);
		txtNewTarget.setVisible(!visible);
		manualControlBox.setVisible(!visible);
	}

	private class TextFieldHandler implements ActionListener
	{

		@Override
		public void actionPerformed(ActionEvent e)
		{

			if (e.getSource() == btnGo)
			{ // button Go pressed

				boolean validInput = true;

				try
				{
					currentTargetFloor = Integer.parseInt(inputTargetFloor.getText());

					if (currentTargetFloor < minElevatorFloor || currentTargetFloor > maxElevatorFloor)
					{

						// the user is able to go to -0 but cannot see a problem
						// with that
						// tell the user the input was out of bounds and has
						// been reset
						validInput = false;
						JOptionPane.showMessageDialog(jplLeftPanel,
							"Invalid input, the number you have choosen is not within the avaiable floors!");
					}
				}
				catch (Exception q)
				{

					// tell the user that the input is not valid eg. not a
					// number
					validInput = false;
					JOptionPane.showMessageDialog(jplLeftPanel,
						"Invalid input, please use a number within the avaiable floors!");

				}
				// newTargetFloor for the control center

				if(validInput)
				{
					int temp = currentTargetFloor - 1;
					manualControl.manualControl(currentElevatorIndex, temp);

					updateTextFields();
				}

			}
			else if (e.getSource() == btnChange)
			{ // button Change pressed

				if (intManualOrAuto == 0)
				{

					intManualOrAuto = 1;
					manualControl.changeControlMode(currentElevatorIndex,
						ControlMode.AUTOMATIC);
				}
				else
				{

					intManualOrAuto = 0;
					manualControl.changeControlMode(currentElevatorIndex,
						ControlMode.MANUAL);

				}

				updateTextFields();

			}
			else if (e.getSource() == inputTargetFloor)
			{ // enter in
				// inputField
				try
				{
					int tempcurrentTargetFloor = currentTargetFloor;
					currentTargetFloor = Integer.parseInt(e.getActionCommand());

					if (currentTargetFloor < minElevatorFloor || currentTargetFloor > maxElevatorFloor)
					{

						currentTargetFloor = tempcurrentTargetFloor;
						// the user is able to go to -0 but cannot see a problem
						// with that
						// tell the user the input was out of bounds and has
						// been reset
						JOptionPane.showMessageDialog(jplLeftPanel,
							"Invalid input, the number you have choosen is not within the avaiable floors!");

					}
				}
				catch (Exception q)
				{

					// tell the user that the input is not valid eg. not a
					// number
					JOptionPane.showMessageDialog(jplLeftPanel,
						"Invalid input, please use a number within the avaiable floors!");

				}

				try
				{
					int temp = currentTargetFloor - 1;
					manualControl.manualControl(currentElevatorIndex, temp);
				}
				catch (Exception w)
				{

					JOptionPane.showMessageDialog(jplLeftPanel,
						"Unable to connect to ECC :" + w.getMessage());

				}

				updateTextFields();
			}
			else if (e.getSource() == manualControlBox)
			{
				if (manualControlBox.getSelectedItem() != elevators.get(
					currentElevatorIndex).getCommittedDirection())
				{
					manualControl.manualDirection(currentElevatorIndex,
						(DirectionType) manualControlBox.getSelectedItem());
				}
				// DirectionType.valueOf(()
				// if == 0)
				// {
				//
				// }
				// else if (manualControlBox.getSelectedIndex() == 1)
				// {
				//
				// }
				// else if (manualControlBox.getSelectedIndex() == 2)
				// {
				//
				// }
			}
		}
	}

}
